package com.ctg.behavior.calc.impala.transfer.userlist;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.ctg.behavior.calc.common.CtSQLParam;
import com.ctg.behavior.calc.impala.CtSQLTransfer;
import com.ctg.behavior.calc.impala.builder.usergroups.CtUGCalcReportBuilder;
import com.ctg.behavior.calc.impala.report.uesrgroups.CtCalcUGUBRuleReport;
import com.ctg.behavior.calc.impala.report.uesrgroups.CtCalcUGUSRuleReport;
import com.ctg.behavior.calc.impala.report.userlist.CtCalcUGULReport;
import com.ctg.behavior.calc.impala.transfer.usergroups.CtUGUBRuleTransfer;
import com.ctg.behavior.calc.impala.transfer.usergroups.CtUGUPRuleTransfer;
import com.ctg.behavior.calc.impala.transfer.usergroups.CtUGUSRuleTransfer;
import com.ctg.behavior.calc.utils.CtCalcPropertyUtils;
import com.ctg.behavior.calc.utils.CtCalcSQLUtils;
import com.ctg.behavior.common.calc.CtCalc;
import com.ctg.behavior.common.calc.CtCalcSortInfo;
import com.ctg.behavior.common.usergroups.CtUGRuleContent;
import com.ctg.behavior.common.usergroups.CtUGUserPropertyRule;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class CtUGUserListTransfer implements CtSQLTransfer {

	@Autowired
	private CtUGUPRuleTransfer upRuleTransfer;
	@Autowired
	private CtUGUBRuleTransfer ubRuleTransfer;
	@Autowired
	private CtUGUSRuleTransfer usRuleTransfer;
	@Autowired
	private CtUGCalcReportBuilder ugCalcReportBuilder;

	/******************************************************
	 * @apiNote: 本接口用于筛选设备ID；筛选条件(规则)有：用户属性、用户行为、用户行为序列
	 * @apiNote: 三个规则关系为：or/and
	 * @apiNote:
	 */
	@Override
	public String doTransfer(CtCalc calcObject, CtSQLParam sqlParam) {

		if (!(calcObject instanceof CtCalcUGULReport)) {
			log.warn("calcObject is not CtCalcUGULReport, class={}", calcObject.getClass());
			log.warn("calcObject: {}", JSON.toJSON(calcObject));
			return "";
		}
		CtCalcUGULReport ugulReport = (CtCalcUGULReport) calcObject;
		log.info("ugulReport={}", JSON.toJSONString(ugulReport));

		CtUGRuleContent ugRuleContent = ugulReport.getRuleContentList().get(0);

		// 此层SQL的表查询别名
		String thisAlias = "ugul";
		String userAlias = "uguser";

		StringBuilder impalaSQL = new StringBuilder();
		{
			// 1. SELECT部分; 若profiles数组不为空,则需要关联user表
			//impalaSQL.append(" SELECT DISTINCT ");
			impalaSQL.append(" SELECT ");
			impalaSQL.append(thisAlias).append(".user_id AS userId ");
			impalaSQL.append(" , max(").append(thisAlias).append(".device_id) AS deviceId ");
			for (String profile : ugulReport.getProfiles()) {
				String userProperty = CtCalcPropertyUtils.getProperty(profile);
				impalaSQL.append(" , ").append(userAlias).append(".").append(userProperty).append(" AS ").append(userProperty);
			}
		}
		{
			// 2. 根据APP_ID来决定查询哪个表; 若profiles数组不为空,则需要关联user表
			impalaSQL.append(" FROM ");
			String appId = ugulReport.getAppId();
			impalaSQL.append(" a_event_parquet_").append(appId).append(" ").append(thisAlias);
			// if (!ugulReport.getProfiles().isEmpty()) {
			// 要与user表关联
			impalaSQL.append(" LEFT JOIN ");
			impalaSQL.append(" a_user_kudu_").append(appId).append(" ").append(userAlias);
			impalaSQL.append(" ON ").append(userAlias).append(".user_id = ").append(thisAlias).append(".user_id ");
			// }
			impalaSQL.append(" WHERE ");
		}
		boolean hasRuleCondition = false;
		String relation = ugRuleContent.getRelation();
		relation = relation.toUpperCase();
		{
			// 3. 用户属性满足条件
			CtUGUserPropertyRule userPropertyRule = ugRuleContent.getUserPropertyRule();
			String sqlUPRule = upRuleTransfer.doTransfer(userPropertyRule, CtSQLParam.createAliasParam(userAlias));
			log.info("sqlUserProperties: {}", sqlUPRule);
			if (!CtCalcSQLUtils.isEmptyCondtions(sqlUPRule)) {
				impalaSQL.append(sqlUPRule);
				hasRuleCondition = true;
			}
		}
		{
			// 4. 用户行为满足条件
			CtCalcUGUBRuleReport ubRuleReport = ugCalcReportBuilder.buildUGUBRuleReport(ugulReport);
			String sqlUBRule = ubRuleTransfer.doTransfer(ubRuleReport, CtSQLParam.createParam());
			log.info("sqlUserBehavior: {}", sqlUBRule);
			if (!CtCalcSQLUtils.isEmptyCondtions(sqlUBRule)) {
				if(hasRuleCondition) {
					impalaSQL.append(relation);
				} else {
					hasRuleCondition = true;
				}
				impalaSQL.append(" ").append(thisAlias).append(".user_id IN ( ");
				impalaSQL.append(sqlUBRule);
				impalaSQL.append(" ) ");
			}
		}
		{
			// 5. 行为序列
			CtCalcUGUSRuleReport usRuleReport = ugCalcReportBuilder.buildUGUSRuleReport(ugulReport);
			String sqlUSRule = usRuleTransfer.doTransfer(usRuleReport, CtSQLParam.createParam());
			log.info("sqlUserSequence: {}", sqlUSRule);
			if (!CtCalcSQLUtils.isEmptyCondtions(sqlUSRule)) {
				if(hasRuleCondition) {
					impalaSQL.append(relation);
				}
				// impalaSQL.append(" device_id IN ( ");
				impalaSQL.append(" ").append(thisAlias).append(".user_id IN ( ");
				impalaSQL.append(sqlUSRule);
				impalaSQL.append(" ) ");
			}
		}

		// 6. GROUP BY
		{
			impalaSQL.append(" GROUP BY ");
			impalaSQL.append(thisAlias).append(".user_id ");
			for (String profile : ugulReport.getProfiles()) {
				String userProperty = CtCalcPropertyUtils.getProperty(profile);
				impalaSQL.append(" , ").append(userAlias).append(".").append(userProperty);
			}
		}

		// 7. 排序、LIMIT
		CtCalcSortInfo sortInfo = ugulReport.getSortInfo();
		if (!StringUtils.isEmpty(sortInfo.getSortProfile())) {
			String userProperty = CtCalcPropertyUtils.getProperty(sortInfo.getSortProfile());
			impalaSQL.append(" ORDER BY ").append(userProperty);
			if (sortInfo.getSortAsc()) {
				impalaSQL.append(" ASC ");
			} else {
				impalaSQL.append(" DESC ");
			}
		} else {
			impalaSQL.append(" ORDER BY ").append(thisAlias).append(".user_id ");;
		}

		// 8. LIMIT 或 分页
		if (null != ugulReport.getPage() && ugulReport.getLimit() >= 0) {
			Integer currentPage = ugulReport.getPage().getCurrentPage();
			currentPage = currentPage - 1;
			currentPage = (currentPage >= 0 ? currentPage : 0);
			Integer startPos = currentPage * ugulReport.getPage().getPageSize();
			Integer endPos = (1 + currentPage) * ugulReport.getPage().getPageSize();
			if (endPos > ugulReport.getLimit() && ugulReport.getLimit() != 0) {
				endPos = ugulReport.getLimit();
			}
			Integer limitSize = endPos - startPos;
			limitSize = limitSize > 0 ? limitSize : 0;
			impalaSQL.append(" LIMIT ").append(limitSize).append(" OFFSET ").append(startPos);
		}

		String retSQL = impalaSQL.toString();
		log.info("CalcSQL={}", retSQL);

		return retSQL;
	}

}
